package org.bwapi.bridge.model;

import java.util.Set;

import org.apache.commons.collections15.Transformer;
import org.bwapi.bridge.swig.SWIGTYPE_p_TilePosition;
import org.bwapi.bridge.swig.SWIGTYPE_p_std__setT_BWAPI__TilePosition_t;
import org.bwapi.bridge.swig.SWIGTYPE_p_std__setT_TilePosition_t;
import org.bwapi.bridge.swig.TilePositionSet;
import org.bwapi.bridge.swig.TilePositionSetIterator;
import org.bwapi.bridge.swig.bridge;
import org.cretz.swig.collection.NativeSet;
import org.cretz.swig.util.SwigUtils;



/**
 * Tile position
 * 
 * @see <a href="http://code.google.com/p/bwapi/wiki/Misc">TilePosition</a>
 * 
 * @author Chad Retz
 */
public class TilePosition {
	private static final Transformer<TilePosition, org.bwapi.bridge.swig.TilePosition> FROM = 
		new Transformer<TilePosition, org.bwapi.bridge.swig.TilePosition>() {
			@Override
			public org.bwapi.bridge.swig.TilePosition transform(TilePosition position) {
				return position.getPosition();
			}
		};
		
	private static final Transformer<org.bwapi.bridge.swig.TilePosition, TilePosition> TO = 
		new Transformer<org.bwapi.bridge.swig.TilePosition, TilePosition>() {
			@Override
			public TilePosition transform(org.bwapi.bridge.swig.TilePosition position) {
				return new TilePosition(position);
			}
		};

	public static final TilePosition INVALID = new TilePosition(bridge.getTilePositionInvalid());
	public static final TilePosition NONE = new TilePosition(bridge.getTilePositionNone());
	public static final TilePosition UNKNOWN = new TilePosition(bridge.getTilePositionUnknown());
	
	static Set<TilePosition> newSet(SWIGTYPE_p_std__setT_BWAPI__TilePosition_t nativeSet) {
		return new NativeSet<TilePosition, org.bwapi.bridge.swig.TilePosition>(
				org.bwapi.bridge.swig.TilePosition.class, TilePositionSetIterator.class, 
				nativeSet, TilePositionSet.class, FROM, TO);
	}
	
	//hope this works...
	static Set<TilePosition> newSet(SWIGTYPE_p_std__setT_TilePosition_t nativeSet) {
		return newSet(SwigUtils.getSwigPointer(SwigUtils.getSwigPointer(nativeSet), 
				false, SWIGTYPE_p_std__setT_BWAPI__TilePosition_t.class));
	}

	private final org.bwapi.bridge.swig.TilePosition position;
	
	TilePosition(org.bwapi.bridge.swig.TilePosition position) {
		this.position = position;
	}
	
	TilePosition(SWIGTYPE_p_TilePosition pointer) {
		this(SwigUtils.getSwigPointer(SwigUtils.getSwigPointer(pointer), 
				false, org.bwapi.bridge.swig.TilePosition.class));
	}
	
	public TilePosition() {
		this(new org.bwapi.bridge.swig.TilePosition());
	}
	
	public TilePosition(Position position) {
		this(new org.bwapi.bridge.swig.TilePosition(position.getPosition()));
	}
	
	public TilePosition(int x, int y) {
		this(new org.bwapi.bridge.swig.TilePosition(x, y));
	}
	
	org.bwapi.bridge.swig.TilePosition getPosition() {
		return position;
	}
	
	SWIGTYPE_p_TilePosition getPointer() {
		return SwigUtils.getSwigPointer(position, SWIGTYPE_p_TilePosition.class);
	}

	public boolean opEquals(TilePosition other) {
		return position.opEquals(other.getPosition());
	}

	public boolean opNotEquals(TilePosition other) {
		return position.opNotEquals(other.getPosition());
	}

	public boolean opLessThan(TilePosition other) {
		return position.opLessThan(other.getPosition());
	}

	public TilePosition opPlus(TilePosition other) {
		return new TilePosition(position.opPlus(other.getPosition()));
	}

	public TilePosition opMinus(TilePosition other) {
		return new TilePosition(position.opMinus(other.getPosition()));
	}

	public TilePosition opAdd(TilePosition other) {
		return new TilePosition(position.opAdd(other.getPosition()));
	}

	public TilePosition opSubtract(TilePosition other) {
		return new TilePosition(position.opSubtract(other.getPosition()));
	}

	public double getDistance(TilePosition other) {
		return position.getDistance(other.getPosition());
	}

	public double getLength() {
		return position.getLength();
	}

	public boolean isValid() {
		return position.isValid();
	}
	
	//TODO: add util to set int from pointer
	
	public int x() {
		return position.xConst();
	}

	public int y() {
		return position.yConst();
	}
	
	@Override
	public boolean equals(Object obj) {
		return obj instanceof TilePosition &&
				opEquals((TilePosition) obj);
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x();
		result = prime * result + y();
		return result;
	}
}
